package ru.arriah.common.ejb;

import java.rmi.*;
import java.util.*;
import javax.ejb.*;
import javax.naming.*;
import ru.arriah.common.ejb.help.*;

public class SequenceService extends GenericSessionBean {
   protected final static int BLOCK_SIZE = 10;
   protected final static int RETRY_COUNT = 5;
   protected SequenceLocalHome sequenceHome;
   protected HashMap<String, KeyBlock> keyBlocks;

   public SequenceService() {
      super();
      sequenceHome = null;
      keyBlocks = new HashMap<String, KeyBlock>();
   }

   public void setSessionContext(
      SessionContext sessionContext
   ) throws EJBException, RemoteException {
      super.setSessionContext(sessionContext);

      try {
         sequenceHome =
            (SequenceLocalHome) (new InitialContext()).lookup(
               "java:comp/env/ejb/Sequence"
            );
      } catch (Exception e) {
         handleException(e, "setSessionContext");
         throw new EJBException(e);
      }
   }

   protected KeyBlock getNextBlock(SequenceLocalObject sequence) {
      KeyBlock result = null;
      int take = 0;
      boolean success = false;

      while (take < RETRY_COUNT && !success) {
         try {
            result = sequence.getNextBlock(BLOCK_SIZE);
            success = true;
         } finally {
            take++;
         }
      }

      if (result == null) {
         throw new EJBException(
            "Failed to get next block for sequence " + sequence.getName()
         );
      }

      return result;
   }

   public Integer getNextKeyFor(String entityName) {
      try {
         int result;
         KeyBlock keyBlock = keyBlocks.get(entityName);

         if (keyBlock == null || !keyBlock.hasNext()) {
            SequenceLocalObject sequence =
               sequenceHome.findByName(entityName);

            keyBlock = getNextBlock(sequence);
            keyBlocks.put(entityName, keyBlock);
         }

         result = new Integer(keyBlock.move());
         return result;
      } catch (Exception e) {
         handleException(e, "getNextKeyFor");
         throw new EJBException(e);
      }
   }
}
